package com.util;

import java.lang.*;
import java.lang.reflect.Method;
import java.lang.reflect.Field;
import java.sql.*;
import java.util.*;



public class BaseDao<T> {
	private static String DRIVER = "com.mysql.jdbc.Driver";
	private static String URL = "jdbc:mysql://localhost/user?characterEncoding=utf-8";
	private static String USER = "root";
	private static String PASSWORD = "930411";
	public static Connection getConn() {
		Connection conn = null;
		try {
			Class.forName(DRIVER);
			conn = DriverManager.getConnection(URL, USER, PASSWORD);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return conn;
	}
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public List<T> query(String sql, Object[] args, Class clazz) {
		Connection conn = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;

		// 存储返回的集合对象
		List<T> list = new ArrayList<T>();
		try {
			// 使用反射获取类的相关信息(实体类的属性--数据库里相应表的字段)
			Field[] fields = clazz.getDeclaredFields();
			Method method = null;
			conn = getConn();
			pstmt = conn.prepareStatement(sql);

			// 如果sql语句有参数用args集合循环给其赋值
			if (args != null && args.length > 0) {
				for (int i = 0; i < args.length; i++) {
					pstmt.setObject(i +1, args[i]);// 参数位置号从1开始
				}
			}
			rs = pstmt.executeQuery();
			// 获取结果集的元数据
			ResultSetMetaData rsmd = rs.getMetaData();// 得到元数据集
			// 获取一共有多少列
			int columnCount = rsmd.getColumnCount();// 得到sql语句到底查询了多少个字段
			while (rs.next()) {
				// 创建一个新对象
				T obj = (T) clazz.newInstance();// 创建一个实例
				// 取出的结果集中列号从1开始
				for (int i = 1; i <= columnCount; i++) {
					String cname = rsmd.getColumnName(i);// 获取每一列[数据表的列名]的名称
					int ctype = rsmd.getColumnType(i);// 获取每一列[数据库表的数据类型]的数据类型
					for (Field f : fields) {
						if (cname.equalsIgnoreCase(f.getName()))// 如果列名和字段名相同
						{
							// 开始封装数据
							String methodName = "set"
									+ f.getName().substring(0, 1).toUpperCase()
									+ f.getName().substring(1);
							// 根据列的type值的类型进行处理
							switch (ctype) {

							case Types.INTEGER:
								method = clazz.getMethod(methodName,
										Integer.class);
								method.invoke(obj, rs.getInt(i));
								break; 
							case Types.VARCHAR:
							case Types.TIMESTAMP:
								
								method = clazz.getMethod(methodName,
										String.class);
								method.invoke(obj, rs.getString(i));

								break;
							}
						}
					}
				}
				list.add(obj);
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			closeAll(null, pstmt, conn);
		}
		return list;
	}

	/**
	 * 增删改
	 * @param sql
	 * @param args
	 * @return
	 */
	public boolean executeSQL(String sql, Object[] args) {
		Connection con = null;
		PreparedStatement ps = null;
		boolean flag = false;
		try {
			con = getConn();
			
			ps = con.prepareStatement(sql);

			if (args != null) {
				for (int i = 1; i <= args.length; i++) {
					ps.setObject(i, args[i - 1]);
				}
			}
			int res = ps.executeUpdate();
			if (res > 0) {
				flag = true;
			}

		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			closeAll(null, ps, con);
		}
		return flag;
	}
	
	
	/**
	 *  关闭连接
	 * @param rs
	 * @param stmt
	 * @param conn
	 */
	public void closeAll(ResultSet rs, Statement stmt, Connection conn) {
		try {
			if (rs != null) {
				rs.close();
			}
			if (stmt != null) {
				stmt.close();
			}
			if (conn != null) {
				conn.close();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

